<?php

/**
 * @Author: lujizhang
 * @Date:   2019-10-16 09:26:11
 * @Last Modified by:   lujizhang
 * @Last Modified time: 2019-11-04 10:37:36
 */

namespace app\api\model;
use think\Db;
use app\common\lib\Aes;
use wxpay\WxPayData\WxPayUnifiedOrder;
use wxpay\WxPayApi;
use app\wxzf\model\JsApiPay;
use app\api\model\WechatThird;

class Wechat extends WechatThird{
    public $wx_app_id='';
    public $wx_app_secret='';
    public $wx_msg_token='';
    
    public $jsTicket = "";
    public $wxApiBase = "https://api.weixin.qq.com/cgi-bin";
    public $accessToken="";
    public $refreshToken = "";
    public $wx_config = [];
    public $wxu_openid="";
    public $wxu_nickname="";
    public $wxu_sex;
    public $wxu_province;
    public $wxu_city;
    public $wxu_country;
    public $wxu_headimgurl;
    public $wxu_unionid;
    


    function __construct($appId=false){
        if($appId){
            $this->wx_app_id = $appId;
            $wx_config = Db::table('sy_wx_auth_info')
                ->where('authorizer_appid="'.$appId.'"')
                ->order('id desc')
                ->find();
            

            if(!empty($wx_config)){
                $this->wx_config['wx_app_id'] = $wx_config['authorizer_appid'];
                $this->wx_config['access_token'] = $wx_config['authorizer_access_token'];
                $this->wx_config['authorizer_refresh_token'] = $wx_config['authorizer_refresh_token'];
                $this->wx_app_id=$wx_config['authorizer_appid'];
                $this->refreshToken = $wx_config['authorizer_refresh_token'];
                $this->accessToken = $wx_config['authorizer_access_token'];

            }
            else{
                subLog('没有配置微信参数','Wechat __construct');
            }
        }
        parent::__construct();
        
    }

    
    /**
     * 获取微信接口调用token
     * @param  [type] $wx_config [description]
     * @return [type]            [description]
     */
    public function getAccessToken($appId){
        if(!empty($this->accessToken)) return $this->accessToken;
        else{
            $accessToken = Db::table('sy_wx_auth_info')
                ->where('authorizer_appid="'.$appId.'"')
                ->value('authorizer_access_token');
            $this->accessToken = $accessToken;
            return $accessToken;
        }
    }

    /**
     * 获取/刷新接口调用令牌
     * authorizer_access_token 有效期为 2 小时
     * 接口调用令牌（authorizer_access_token）失效时，可以使用刷新令牌
     * 需要缓存 authorizer_access_token，避免获取/刷新接口调用令牌的 API 调用触发每日限额。
     * 这里需要建一个计划任务每隔110分钟刷新令牌
     * 计划任务调用此接口
     */
    public function refreshAccessToken($authAppId,$refreshToken){
        $url =$this->wxApiBase.'/component/api_authorizer_token?component_access_token='.$this->component_access_token;
        $data = [
            'component_appid'=>$this->component_appid,
            'authorizer_appid'=>$authAppId,
            'authorizer_refresh_token'=>$refreshToken
        ];
        $res = $this->httpRequest($url,$data);
        
        $content = json_decode($res,true);
        // subLog($url,'refreshAccessToken','wechat');
        // 
        if(empty($content['authorizer_access_token'])){
            subLog($content,'refreshAccessToken','wechat');
            return false;
        }
        else{
            $data = [];
            $data['authorizer_access_token'] = $content['authorizer_access_token'];
            $data['authorizer_refresh_token'] = $content['authorizer_refresh_token'];
            $data['expired'] = Db::raw('date_add(now(),INTERVAL '.$content['expires_in'].' SECOND)');
            $data['update_time'] = Db::raw('now()');
            
            
            $id = Db::table('sy_wx_auth_info')->where('authorizer_appid="'.$authAppId.'"')->value('id');
            if($id){
                Db::table('sy_wx_auth_info')->where('id='.$id)->update($data);
            }
            else{
                Db::table('sy_wx_auth_info')->insert($data);
            }
            return $content;
        }
        
        
    }
    

    /**
     * 非Oauth界面获取用户信息
     * @param $open_id
     * @param $access_token
     * @return mixed
     */
    public function getWxUserInfoFromApi($open_id){
        $url = $this->wxApiBase."/user/info?access_token=".$this->accessToken."&openid=".$open_id."&lang=zh_CN";
        $data = $this->httpRequest($url);
        $userInfo =  json_decode($data,true);
        return $userInfo;
    }

    
    

    public function getPrepayUrl($info,$remake_url=false,$trade_type="NATIVE",$openId=""){
        $curTime = date("YmdHis");
        $url = "";
        $where = 'order_no="'.$info['order_no'].'"';
        $where .=' and time_expire>="'.$curTime.'"';
        $where .=' and trade_type="'.$trade_type.'"';
        $where .=' and total_fee = '.$info['total_amount'];
        $prepayInfo = Db::table('sy_prepay_id')
            ->where($where)
            ->order('id desc')
            ->limit(1)
            ->find();
        if(!empty($prepayInfo) && !$remake_url){
            $result = $prepayInfo;
        }
        else{
            $result = $this->getPrepayUrlFromWechat($info,$trade_type,$openId);
        }

        if($result['return_code']=="SUCCESS"){
            if($result['result_code']=="SUCCESS"){
                if($trade_type=="NATIVE") {
                    $url = $result['code_url'];
                    $url = $this->encryptUrl($url);
                }
                else $url = "";
            }
            else $url = "fail";
        }
        else $url = "fail";
        
        $result['code_url'] = $url;
        
        return $result;
        
    }

    public function getPrepayUrlFromWechat($info,$trade_type="NATIVE",$openId=""){
        // $total_fee = 1;
        $table = "sy_prepay_id";
        $productId = "SA001";
        $goodsTag = "九臻快消";
        $curTime = date("YmdHis");
        $endTime = date("YmdHis", time() + 600);
        $notifyUrl =config('host.wx_pay_notify')."/wxzf/native_notify";
        $tradeType = $trade_type;
        $outTradeNo = $info['order_no'];
        $totalFee = $info['total_amount'];
        $deviceInfo = "JS001";  // 此处应传收费终端

        $payBody = "";
        $payAttach = ""; 
        
        
        $input = new WxPayUnifiedOrder();
        $input->SetBody($payBody);
        $input->SetAttach($payAttach);
        $input->SetOut_trade_no($outTradeNo);
        $input->SetTotal_fee($totalFee);
        $input->SetTime_start($curTime);
        $input->SetTime_expire($endTime);
        $input->SetGoods_tag($goodsTag);
        $input->SetNotify_url($notifyUrl);
        $input->SetTrade_type($tradeType);

        if($trade_type=="JSAPI") {
            $pay_obj = new JsApiPay();
            // $openId = $pay_obj->GetOpenid();
            $input->SetOpenid($openId);
        }
        else {
            $pay_obj = new NativePay();
            $input->SetProduct_id($productId);
        }
        $result = $pay_obj->GetPayUrl($input);

        $result['out_trade_no'] = $outTradeNo;
        $result['time_start'] = $curTime;
        $result['time_expire'] = $endTime;
        $result['device_info'] = $deviceInfo;
        $result['body'] = $payBody;
        // $result['detail'] = $info['order_sn'];
        $result['attach'] = $payAttach;
        $result['total_fee'] = $totalFee;
        // var_dump($result);die();

        if($result['return_code']=="SUCCESS"){
            if($result['result_code']=="SUCCESS"){
                if($trade_type=="JSAPI") $result['jsapi_param'] = $pay_obj->GetJsApiParameters($result);

                // $url = $result['codel_url'];
                if(isset($result['prepay_id']) && !empty($result['prepay_id'])){
                    $prepayInfo = Db::table($table)->where('prepay_id="'.$result['prepay_id'].'"')->find();
                    if(!empty($prepayInfo)){
                        Db::table($table)->where('id='.$prepayInfo['id'])->update($result);
                    }
                    else{
                        $result['order_no'] = $outTradeNo;
                        Db::table($table)->insert($result);
                    }
                }

            }
            else{
                $result['code_url'] = "result_fail";
                subLog($result,$outTradeNo.":".$totalFee." get prepay url error result","error");
                subLog($info,$outTradeNo.":".$totalFee." get prepay url input","error");
                // var_dump($input);
            }
            
        }
        else{
            $result['code_url'] = "request_fail";
            subLog($input,$outTradeNo.":".$totalFee." get prepay url request_fail","error");
        }

        return $result;
    }

    public function encryptUrl($url){
        $aes = new Aes;
        $url = $aes->encrypt($url);
        $url = urlencode($url);
        return $url;
    }

    function httpRequest($url,$data = null,$responseHeader = false){
        $curl = curl_init();
       
        curl_setopt($curl, CURLOPT_HEADER,$responseHeader);
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); // 对认证证书来源的检查
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2); // 从证书中检查SSL加密算法是否存在
        if(\is_array($data)) $data = \json_encode($data,JSON_UNESCAPED_UNICODE);
        if (!empty($data)){
            curl_setopt($curl, CURLOPT_POST, 1);
            curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
        }
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($curl, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 5.1; rv:9.0.1) Gecko/20100101 Firefox/9.0.1');
        $output = curl_exec($curl);
        curl_close($curl);
        //subLog("weixinapi====".$url,$output);
        return $output;
    }

}
